:- module(dbfillin, [main/0], [pillow]).

:- use_module(library(terms)).
:- use_module(library(streams)).
:- use_module(library(read)).
:- use_module(library(system), 
        [
            time/1,
            make_directory/1,
            make_dirpath/1,
            file_exists/1]).
:- use_module(library('make/system_extra'), [copy_file/2]).

:- use_module(lc_database_impl).
:- use_module(term_list_conversion).

%% Just to make backups! (need pers_data_dir/1)
%:- use_module(amos(configuration)).    

:- use_package(hiord).
:- use_module(library(hiordlib)).
:- use_package(functions).

:- data amos_data/8.
:- data rid/1.

main :-
        make_backup,
	get_form_input(Info),
	compute_reply(Info, Form),
	output_html([
			cgi_reply,
			start,
			title('Amos data insertion form'),
			h1('Amos data insertion form'), 
                        \\,
  			--,
			start_form,
			Form,
			input(submit,[value='Send values']),nl,
			input(reset,[value='Reset form']),
			end_form,
			--,
			end
		    ]).

repetition(10).

compute_reply(Info, Form) :-
	min_rows(NumberOfRows),
	collect_rows(1, NumberOfRows, ~repetition, Info, Rows),
        header(Header),
	Form = [
		   begin(table),
		   begin(tbody),
                   Header,
                   nl,
		   Rows,
		   end(table),
		   end(tbody)
	       ],
	divert_data,
	gen_term_desc.

header([
        begin(tr),
               ~map(H, (_(X, Y):- Y = [
                               begin(td), 
                                  begin(strong), 
                                     X, 
                                  end(strong),
                               end(td)])),
        end(tr)]):-
      heading(H).

collect_rows(N, Max,_,_,[]) :-
	N > Max, !.
collect_rows(N, Max, R, Info, [Row, nl|Rs]) :-
	atom_number(Na, N),
	collect_row(Info, Na, Row),
	N1 is N + 1,
        % Check whether we have to add a row of headings.
        (
            R = 0 ->
            Rs = [~header, nl|MoreRows],
            repetition(NextRs)
        ;
            MoreRows = Rs,
            NextRs is R - 1
        ),
	collect_rows(N1, Max, NextRs, Info, MoreRows).

collect_row(Info, RowNumberA, Row) :-
	amos_data_arity(NumberOfFields),
	do_collect_row(1, NumberOfFields, RowNumberA, Info, FieldNames, RowVals),
	(form_empty_list_values(RowVals) ->
	 retrieve_stored_values(RowNumberA, NumberOfFields, FieldNames, Row)
	;
	 update_stored_values(RowNumberA, NumberOfFields, FieldNames, RowVals, Row)).	 

do_collect_row(N,Max,_,_,[],[]) :-
	N > Max, !.
do_collect_row(N, Max, Rna, Info, [FieldName|Fs], [Value|Vs]) :-
	atom_number(Na, N),
	atom_concat([Rna, '_', Na], FieldName),
	N1 is N + 1,
	get_form_value(Info, FieldName, Value0),
	(Value0 = '$empty' -> 
	 Value = ''
	;
	 Value = Value0),
	do_collect_row(N1, Max, Rna, Info, Fs, Vs).

retrieve_stored_values(RowId, Arity, FieldNames, Row) :-
	Arity1 is Arity + 1,
	empty_pred(amos_data, Arity1, RowId, AmosDataP),
	(current_fact(AmosDataP) ->
	 AmosDataP =.. [_,_,Name|Values0],
	 rewrite_1_2_values_l2a(Values0, Values),
	 produce_row(FieldNames, [Name|Values], Row)
	;
         A3 is Arity - 3,
	 n_void(A3, Voids),
	 produce_row(FieldNames, ['','',''|Voids], Row),
	 AmosDataP =.. [amos_data, RowId, '', [], []|Voids],
%	 assertz_fact(AmosDataP)).
	 asserta_fact(AmosDataP)).
	
update_stored_values(RowId, Arity, FieldNames, Values0, Row) :-
	Arity1 is Arity + 1,
	empty_pred(amos_data, Arity1, RowId, EmptyP),
	retract_fact(EmptyP),
	Values0 = [Name|Values1],
	rewrite_1_2_values_a2l(Values1, Values),
	AmosDataP =.. [amos_data, RowId, Name|Values],
	assertz_fact(AmosDataP),
%	asserta_fact(AmosDataP),
	produce_row(FieldNames, Values0, Row).

form_empty_list_values([]).
form_empty_list_values([Value|Vs]):-
        (form_empty_value(Value); Value = '$empty'),
        form_empty_list_values(Vs).

produce_row(Fields, Values, Row) :-
	do_produce_row(Fields, Values, Elements),
	Row = [
		  begin(tr),
		  Elements,
		  end(tr)
	      ].
	
do_produce_row([], [], []).
do_produce_row([FieldName|Fs], [Value|Vs], [Element|Es]) :-
	Element = [
		      begin(td),
		      input(text, [name = FieldName, value = Value]),
		      end(td)
		  ],
	do_produce_row(Fs, Vs, Es).
		      
n_void(0, []).
n_void(N, [''|Voids]) :-
	N1 is N - 1,
	n_void(N1, Voids).

empty_pred(F, A, Id, P) :-
	functor(P, F, A),
	arg(1, P, Id).

revert_data :-
	amos_data_arity(A),
	empty_pred(s_item, A, _, CentralP),
	r_f(CentralP),
	CentralP =.. [_|Values],
	retract_fact(rid(N)),
	atom_number(Na, N),
	P =.. [amos_data, Na|Values],
%	asserta_fact(P),
	assertz_fact(P),
	N1 is N + 1,
	asserta_fact(rid(N1)),
	fail.
revert_data.

divert_data :-
	amos_data_arity(A),
	A1 is A + 1,
	empty_pred(amos_data, A1, _, P),
	P =.. [_,_|Values],
	retract_fact(P),
	CentralP =.. [s_item|Values],
%originally a:
	a_z_f(CentralP),
	fail.
divert_data.

rewrite_1_2_values_l2a([R0,P0|Values], [R,P|Values]) :-
	term_list_to_atom(R0, R),
	term_list_to_atom(P0, P).
rewrite_1_2_values_a2l([R0,P0|Values], [R,P|Values]) :-
	atom_to_term_list(R0, R),
	atom_to_term_list(P0, P).

:- initialization(startup).

startup :-
	asserta_fact(rid(1)),
	revert_data.

heading(['Package name','Provides','Requires','URL','Description','Size','License']).

% Needed to generate an empty form in case the database is empty:
min_rows(122) .

